package com.zjpavt.client.artnet.device;

import com.zjpavt.client.artnet.effect.IEffect;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 受dmx信号控制的灯带
 */
public class StripLight {
    public static final int SIZE_RGB = 3;
    public static final int SIZE_RGBW = 4;

    /**
     * 占据的通道数量
     */
    private int lightChannelSize = SIZE_RGB;

    private List<SingleLight> lightList = new ArrayList<>();
    /**
     * 灯带开始占据的通道号
     */
    private int beginIndex;
    /**
     * 灯带上灯具数量
     */
    private int lightNum;
    /**
     * 灯带所在的域
     */
    private int universe;
    /**
     * 显示的名称
     */
    private String displayName;
    /**
     * 特效配置
     */
    private IEffect effect;

    /**
     *  下一个特效
     */
    private IEffect nextEffect;
    /**
     * 超时时间
     */
    private long outTime = Long.MAX_VALUE;
    /**
     *
     * @param beginIndex
     * @param lightNum
     * @param universe
     * @param displayName
     */


    public StripLight(int beginIndex, int lightNum, int universe,String displayName) {
        this(beginIndex, lightNum, universe);
        this.displayName = displayName;
    }
    public StripLight(int beginIndex, int lightNum, int universe,String displayName,IEffect effect) {
        this(beginIndex, lightNum, universe,displayName);
    }
    public StripLight(int beginIndex, int lightNum, int universe) {
        this.beginIndex = beginIndex;
        this.lightNum = lightNum;
        int channelIndex = beginIndex;
        for (int i = 0; i < lightNum; i++) {
            lightList.add(new SingleLight(channelIndex, universe));
            channelIndex += lightChannelSize;
        }
    }

    public StripLight(String configText,IEffect effect) {
        this(configText);
        this.effect = effect;
    }

    public StripLight() {
    }

    public StripLight(String configText) {
        String[] configParameter = configText.split(",");
        String[] nameAndValue;
        for (String parameter : configParameter) {
            if (parameter.contains(":")) {
                nameAndValue = parameter.split(":");
                String name = nameAndValue[0];
                String value = nameAndValue[1];
                switch (name) {
                case "beginIndex":
                    this.beginIndex = Integer.parseInt(value);
                    break;
                case "lightNum":
                    this.lightNum = Integer.parseInt(value);
                    break;
                case "universe":
                    this.universe = Integer.parseInt(value);
                    break;
                default:
                    break;
                }
            }
        }
        this.beginIndex = beginIndex;
        this.lightNum = lightNum;
        int channelIndex = beginIndex;
        for (int i = 0; i < lightNum; i++) {
            lightList.add(new SingleLight(channelIndex, universe));
            channelIndex += lightChannelSize;
        }
    }
    public int getSingleLightChannelSize() {
        return lightChannelSize;
    }

    public int getBeginIndex() {
        return beginIndex;
    }

    public int getLightNum() {
        return lightNum;
    }

    public int getUniverse() {
        return universe;
    }

    public void setLightColor(int index, byte[] color) {
        this.lightList.get(index).setColor(color);
    }

    public byte[] getLightColor(int index) {
        return this.lightList.get(index).getColor();
    }
    public int getAllChannelSize() {
        return this.lightChannelSize * this.getLightNum();
    }

    public List<SingleLight> getLightList() {
        return lightList;
    }

    /**
     * 获取所有数据
     */
    public byte[] getAllData() {
        byte[] allBytes = new byte[getAllChannelSize()];
        for (int i = 0; i < getLightNum(); i++) {
            System.arraycopy(getLightColor(i),0,allBytes,i* getSingleLightChannelSize(), getSingleLightChannelSize());
        }
        return allBytes;
    }

    /**
     * 不含这个Index 是下一个灯带的beginIndex
     * @return
     */
    public int getEndIndex() {
        return beginIndex + lightChannelSize * lightNum;
    }

    public byte[] append2DmxData(byte[] dmxData) {
        if (System.currentTimeMillis() > outTime) {
            this.effect = nextEffect;
            this.outTime = Long.MAX_VALUE;
        }
        System.arraycopy(getAllData(),0,dmxData,getBeginIndex(),getAllChannelSize());
        return dmxData;
    }
    public boolean existActiveTimeEffect() {
        return outTime != Long.MAX_VALUE;
    }

    /**
     * 当前特效是有时效的 在时效结束后修改为设定效果
     * @param effect
     */
    public void appendEffectWhenTimeOut(IEffect effect) {
        if (existActiveTimeEffect()) {
            this.nextEffect = effect;
        } else {
            this.effect = effect;
        }
    }

    /**
     * 修改为当前特效 无时效
     * @param effect
     */
    public void changeEffect(IEffect effect) {
        this.effect = effect;
        this.outTime = Long.MAX_VALUE;
    }

    /**
     * 修改为某种时效效果，没有设置下一个效果 不推荐使用
     * @param effect
     * @param lastTime
     */
    public void changeTimeEffect(IEffect effect, long lastTime) {
        this.effect = effect;
        outTime = isLongMaxElseAddTimeMill(lastTime);
    }

    /**
     * 在当前时效指令执行完毕后执行
     * @param effect
     */
    public void changeAfterTimeEffect(IEffect effect) {
        if (existActiveTimeEffect()) {
            this.nextEffect = effect;
        } else {
            this.effect = effect;
        }
    }

    public void changeTimeEffect(IEffect effect, long lastTime, IEffect nextEffect) {
        this.nextEffect = nextEffect;
        this.effect = effect;
        outTime = isLongMaxElseAddTimeMill(lastTime);
    }

    private long isLongMaxElseAddTimeMill(long time) {
        if (time == Long.MAX_VALUE) {
            return time;
        } else {
            return time + System.currentTimeMillis();
        }
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public IEffect getEffect() {
        return effect;
    }

    public void setEffect(IEffect effect) {
        this.effect = effect;
        effect.setOwner(this);
    }

    public IEffect getNextEffect() {
        return nextEffect;
    }

    public void setNextEffect(IEffect nextEffect) {
        this.nextEffect = nextEffect;
    }

    public long getOutTime() {
        return outTime;
    }

    /**
     * 设置超时时间 超时切换到下一个节目
     * @param outTime
     */
    public void setOutTime(long outTime) {
        if (outTime == Long.MAX_VALUE) {
            this.outTime = Long.MAX_VALUE;
        }
        this.outTime =isLongMaxElseAddTimeMill(outTime);
    }

    public void setOutTimeNoChange(long outTime) {
        this.outTime = outTime;
    }
}
